import Web3 from "web3";
import {FailedNotice, SuccessNotice} from "../../components/Notice";
import {useEffect, useRef, useState} from "react";
import {Button, Divider, Input, Table } from "antd";
import Title from "antd/es/typography/Title";

/*
* 智能合约
* 投票
* */

let web3;
let contract;
let abi = [
    {
        "inputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "name": "CandidateList",
        "outputs": [
            {
                "internalType": "bytes32",
                "name": "",
                "type": "bytes32"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "bytes32",
                "name": "",
                "type": "bytes32"
            }
        ],
        "name": "Candidates",
        "outputs": [
            {
                "internalType": "uint8",
                "name": "",
                "type": "uint8"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "bytes32",
                "name": "candidate",
                "type": "bytes32"
            }
        ],
        "name": "addCandidate",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "bytes32",
                "name": "candidate",
                "type": "bytes32"
            }
        ],
        "name": "checkCandidate",
        "outputs": [
            {
                "internalType": "bool",
                "name": "",
                "type": "bool"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [],
        "name": "getCandidateList",
        "outputs": [
            {
                "internalType": "bytes32[]",
                "name": "",
                "type": "bytes32[]"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "bytes32",
                "name": "candidate",
                "type": "bytes32"
            }
        ],
        "name": "getVoteTotalFor",
        "outputs": [
            {
                "internalType": "uint8",
                "name": "",
                "type": "uint8"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "bytes32",
                "name": "candidate",
                "type": "bytes32"
            }
        ],
        "name": "voteForCandidate",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    }
];
let contractAddress = "0xc7713E224fD58d1b677D476d891B51f61b83CB1f";


function Vote() {
    useEffect(() => {
        // init()
        console.log("hook");
        init();

        queryVoteInfo();
    }, [])

    const columns = [
        {
            title: '候选人',
            dataIndex: 'name',
            key: 'name',
        },
        {
            title: '当前票数',
            dataIndex: 'count',
            key: 'count',
        },
        {
            title: "操作",
            render: (text, record) => (
                <Button onClick={() => {
                    vote(record.name)
                }}>投票 </Button>
            )
        }
    ];

    const newNameObj = useRef("")
    const [tableData, setTableData] = useState([])

    // 增加一个候选人
    const addCandidate = () => {
        metaMaskAuth(); // 检查授权

        let newData = newNameObj.current.state.value;
        let hexStr = web3.utils.utf8ToHex(newData);
        contract.methods.addCandidate(hexStr).send({from: web3.eth.defaultAccount}).then((res) => {
            console.log(res);
            SuccessNotice("交易Hash" + res.transactionHash, 1);

            queryVoteInfo();    // 刷新表格信息
        }, (err) => {
            FailedNotice(err.message, 5);
        })
    }
    // 查询当前信息，并刷新表格
    const queryVoteInfo = () => {

        metaMaskAuth();

        contract.methods.getCandidateList().call({from: web3.eth.defaultAccount}).then(async function (v) {

            setTableData([]);    // 重置

            let tempList = [];
            for (let i = 0; i < v.length; i++) {
                let json = await getVoteTotalFor(v[i], i)
                tempList.push(json)
            }
            setTableData(tempList);

        })
    }
    // 用名字去查询票数
    const getVoteTotalFor = (name, index) => {
        return new Promise(((resolve, reject) => {
            contract.methods.getVoteTotalFor(name).call().then((voteCount) => {
                let nameStr = web3.utils.hexToUtf8(name)
                resolve({
                    key: index,
                    name: nameStr,
                    count: voteCount
                })
            }).catch((e) => {
                reject(e)
            })
        }))
    }
    // 用脚投票
    const vote = (name) => {
        metaMaskAuth();

        let hexStr = web3.utils.asciiToHex(name);
        contract.methods.voteForCandidate(hexStr).send({from: web3.eth.defaultAccount}).then((res) => {
            console.log("投票成功", res);
            SuccessNotice("投票成功\n交易Hash" + res.transactionHash, 1);

            queryVoteInfo();    // 刷新表格信息
        }).catch((err) => {
            FailedNotice(err.message, 5);
        })
    }

    return (
        <>
            <Title level={1}>投票合约示例</Title>
            <Title level={4}>路径：/contract/vote.sol</Title>

            <Button onClick={queryVoteInfo} style={{float:'right'}}>刷新</Button>
            <Table columns={columns} dataSource={tableData}/>

            <Divider/>

            <Input ref={newNameObj} style={{width: "auto"}}/>
            <Button type={"primary"} onClick={addCandidate}>添加</Button>

        </>
    )
}

function init() {
    if (window.ethereum) {
        web3 = new Web3(window.ethereum)
    } else {
        FailedNotice("未检测到钱包")
        return;
    }

    contract = new web3.eth.Contract(abi, contractAddress);
}

// 小狐狸metamask钱包授权
function metaMaskAuth() {
    if (!isAuth()) {
        window.ethereum.enable().then(function (accounts) {
            web3.eth.defaultAccount = accounts[0]
            console.log("Metamask 授权成功");
        }).catch(function (err) {
            console.log(err)
            FailedNotice(err.message, 1)
        })
    }
}

function isAuth() {
    return web3.eth.defaultAccount !== null;
}

export default Vote;